package com.laicunba.service.impl;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.laicunba.pojo.BorrowerDO;
import com.laicunba.pojo.CurrentAccountDO;
import com.laicunba.pojo.CurrentAccountItemDO;
import com.laicunba.pojo.JzhAccountDO;
import com.laicunba.pojo.RegistryDO;
import com.laicunba.pojo.UserDO;
import com.laicunba.pojo.WithdrawDO;
import com.laicunba.pojo.vo.CurrentAccountProfitVO;
import com.laicunba.service.BorrowerService;
import com.laicunba.service.CurrentAccountItemService;
import com.laicunba.service.CurrentAccountService;
import com.laicunba.service.RegistryService;
import com.laicunba.service.UserService;
import com.laicunba.service.WithdrawService;
import com.laicunba.service.jzh.JzhAccountService;
import com.laicunba.service.jzh.JzhRemoteTransferBuService;
import com.laicunba.util.AssertUtil;
import com.laicunba.util.CacheUtil;
import com.laicunba.util.DateUtil;
import com.laicunba.util.StringUtil;

import redis.clients.jedis.Jedis;

@Service
public class CurrentAccountServiceImpl extends BaseServiceImpl implements CurrentAccountService {
	private static final Logger LOG = Logger.getLogger(CurrentAccountServiceImpl.class);
	private static final MathContext mc = new MathContext(10, RoundingMode.HALF_DOWN);
	@Autowired
	private UserService userService;
	@Autowired
	private CurrentAccountItemService currentAccountItemService;
	@Autowired
	private WithdrawService withdrawService;
	@Autowired
	private JzhRemoteTransferBuService jzhRemoteTransferBuService;
	@Autowired
	private RegistryService registryService;
	@Autowired
	private BorrowerService borrowerService;
	@Autowired
	private JzhAccountService jzhAccountService;

	@Transactional
	@Override
	public boolean createAccount(String uid) {
		AssertUtil.assertTrue(StringUtil.isNotEmpty(uid), "UID_IS_EMPTY");
		CurrentAccountDO currentAccountDO = get(CurrentAccountDO.class, uid);
		AssertUtil.assertTrue(currentAccountDO == null, "CURRENT_ACCOUNT_EXIST");

		UserDO userDO = userService.get(UserDO.class, uid);
		AssertUtil.assertNotNull(userDO, "USER_NOT_EXIST");
		AssertUtil.assertTrue(!"CURRENT_ACCOUNT".equalsIgnoreCase(userDO.gethType()), "H_TYPE_ERROR");
		AssertUtil.assertTrue(userService.update2CurrentAccount(uid), "UPDATE_2_CURRENT_ACCOUNT_FAIL");

		currentAccountDO = new CurrentAccountDO();
		currentAccountDO.setId(uid);
		currentAccountDO.setBalance(BigDecimal.ZERO);
		currentAccountDO.setStatus("enable");
		AssertUtil.assertTrue(create(currentAccountDO));
		return true;
	}

	@Transactional
	@Override
	public CurrentAccountItemDO add(String uid, BigDecimal amount, String mark, String summary) {
		return add0(uid, amount, mark, summary, null);
	}

	private CurrentAccountItemDO add0(String uid, BigDecimal amount, String mark, String summary, String id) {
		AssertUtil.assertTrue(StringUtil.isNotEmpty(uid), "UID_IS_EMPTY");
		AssertUtil.assertNotNull(amount, "AMOUNT_IS_NULL");
		AssertUtil.assertTrue(amount.compareTo(BigDecimal.ZERO) > 0, "AMOUNT_LESS_0");
		CurrentAccountDO currentAccountDO = get(CurrentAccountDO.class, uid);
		AssertUtil.assertNotNull(currentAccountDO, "CURRENT_ACCOUNT_NOT_EXIST");

		CurrentAccountItemDO currentAccountItemDO = new CurrentAccountItemDO();
		currentAccountItemDO.setType("IN");
		currentAccountItemDO.setId(id);
		currentAccountItemDO.setAccountId(currentAccountDO.getId());
		currentAccountItemDO.setMark(mark);
		currentAccountItemDO.setSummary(summary);
		currentAccountItemDO.setAmount(amount);
		currentAccountItemDO.setBalance(currentAccountDO.getBalance().add(amount).setScale(2, RoundingMode.DOWN));
		AssertUtil.assertTrue(currentAccountItemService.create(currentAccountItemDO), "CREATE_CURRENT_ACCOUNT_ITEM_FAIL");
		AssertUtil.assertTrue(updateBalance(currentAccountDO.getId(), currentAccountDO.getBalance(), currentAccountItemDO.getBalance()), "UPDATE_BALANCE_FAIL");
		return currentAccountItemDO;
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	private boolean updateBalance(String accountId, BigDecimal oldBalance, BigDecimal newBalance) {
		Map map = new HashMap();
		map.put("accountId", accountId);
		map.put("oldBalance", oldBalance);
		map.put("newBalance", newBalance);
		return updateDao.update("CURRENT_ACCOUNT.updateBalance", map) == 1;
	}

	@Transactional
	@Override
	public CurrentAccountItemDO subtract(String uid, BigDecimal amount, String mark, String summary) {
		AssertUtil.assertTrue(StringUtil.isNotEmpty(uid), "UID_IS_EMPTY");
		AssertUtil.assertNotNull(amount, "AMOUNT_IS_NULL");
		AssertUtil.assertTrue(amount.compareTo(BigDecimal.ZERO) > 0, "AMOUNT_LESS_0");
		CurrentAccountDO currentAccountDO = get(CurrentAccountDO.class, uid);
		AssertUtil.assertNotNull(currentAccountDO, "CURRENT_ACCOUNT_NOT_EXIST");
		AssertUtil.assertTrue(currentAccountDO.getBalance().compareTo(amount) >= 0, "BALANCE_NOT_ENOUGH");

		CurrentAccountItemDO currentAccountItemDO = new CurrentAccountItemDO();
		currentAccountItemDO.setType("OUT");
		currentAccountItemDO.setAccountId(currentAccountDO.getId());
		currentAccountItemDO.setMark(mark);
		currentAccountItemDO.setSummary(summary);
		currentAccountItemDO.setAmount(amount);
		currentAccountItemDO.setBalance(currentAccountDO.getBalance().subtract(amount).setScale(2, RoundingMode.DOWN));
		AssertUtil.assertTrue(currentAccountItemService.create(currentAccountItemDO), "CREATE_CURRENT_ACCOUNT_ITEM_FAIL");
		AssertUtil.assertTrue(updateBalance(currentAccountDO.getId(), currentAccountDO.getBalance(), currentAccountItemDO.getBalance()), "UPDATE_BALANCE_FAIL");
		return currentAccountItemDO;
	}

	@Override
	public BigDecimal countOneDayProfit(BigDecimal balance, BigDecimal rate) {
		return rate.divide(BigDecimal.valueOf(36500), mc).multiply(balance, mc).setScale(2, RoundingMode.DOWN);
	}

	@Transactional
	@Override
	public boolean incrDailyProfit(String uid, BigDecimal rate) {
		CurrentAccountDO currentAccountDO = get(CurrentAccountDO.class, uid);
		AssertUtil.assertNotNull(currentAccountDO, "CURRENT_ACCOUNT_NOT_EXIST");
		if (currentAccountDO.isProfitLocker()) {
			return false;
		}
		BigDecimal profit = countOneDayProfit(currentAccountDO.getBalance(), rate);
		if (profit.compareTo(BigDecimal.ZERO) == 0) {
			LOG.info(String.format("[tag:INCR_DAILY_PROFIT,uid:%s,balance:%s,profit:0]", uid, currentAccountDO.getBalance()));
		} else {
			AssertUtil.assertNotNull(add0(uid, profit, "PROFIT", null, currentAccountDO.getId() + "." + DateUtil.formatDate(new Date())), "ADD_PROFIT_FAIL");
			LOG.info(String.format("[tag:INCR_DAILY_PROFIT,uid:%s,balance:%s,profit:%s]", uid, currentAccountDO.getBalance(), profit));
		}
		AssertUtil.assertTrue(updateDao.update("CURRENT_ACCOUNT.updateProfitLocker", uid) == 1, "UPDATE_PROFIT_LOCKER_FAIL");
		return true;
	}

	@Override
	public BigDecimal getBalance(String uid) {
		return queryDao.selectOne("CURRENT_ACCOUNT.getBalance", uid);
	}

	@Transactional
	@Override
	public String withdrawApply(WithdrawApplyParam param) {
		AssertUtil.assertTrue(StringUtil.isNotEmpty(param.getUserId(), param.getPid(), param.getHolder(), param.getBankName(), param.getBankCode(), param.getBankCardNo()), "PARAM_ERROR");
		AssertUtil.assertNotNull(param.getWithdrawAmount(), "WITHDRAW_AMOUNT_NULL");
		AssertUtil.assertTrue(param.getWithdrawAmount().compareTo(BigDecimal.ZERO) > 0, "WITHDRAW_AMOUNT_TOO_SMALL");
		UserDO userDO = userService.get(UserDO.class, param.getUserId());
		AssertUtil.assertNotNull(userDO, "USER_NOT_EXIST");
		AssertUtil.assertTrue(userService.isUsedCurrentAccount(userDO.gethType()), "NOT_ENABLE_CURRENT_ACCOUNT");

		String dangerCode = userService.testDangerous(userDO.getId());
		AssertUtil.assertTrue(dangerCode == null, dangerCode);

		BigDecimal balance = getBalance(userDO.getId());
		AssertUtil.assertTrue(balance.compareTo(param.getWithdrawAmount()) >= 0, "BALANCE_NOT_ENOUGH");

		// 扣款
		CurrentAccountItemDO currentAccountItemDO = subtract(userDO.getId(), param.getWithdrawAmount(), "withdraw", "");
		AssertUtil.assertNotNull(currentAccountItemDO, "SUBTRACT_BALANCE_FAIL");
		// 取现申请
		WithdrawDO withdrawDO = new WithdrawDO();
		withdrawDO.setApplyTime(new Date());
		withdrawDO.setId("ca_item-" + currentAccountItemDO.getId());
		withdrawDO.setStatus("apply");
		withdrawDO.setWithdrawPrincipal(param.getWithdrawAmount());
		withdrawDO.setUserId(userDO.getId());
		withdrawDO.setPid(param.getPid());
		withdrawDO.setName(param.getHolder());
		withdrawDO.setBankCardNo(param.getBankCardNo());
		withdrawDO.setBankName(param.getBankName());
		withdrawDO.setBankNo(param.getBankCode());
		withdrawDO.setType("CA");
		withdrawDO.setMark(param.getMark());
		withdrawDO.setSubtractRemainProfit(BigDecimal.ZERO);
		AssertUtil.assertTrue(withdrawService.create(withdrawDO), "CREATE_WITHDRAWDO_ERROR");
		return withdrawDO.getId();
	}

	@Override
	public CurrentAccountProfitVO getProfit(String uid) {
		return queryDao.selectOne("CURRENT_ACCOUNT.getProfit", uid);
	}

	@Override
	public List<String> findNoProfitLockerAccounts(int limit) {
		return queryDao.selectList("CURRENT_ACCOUNT.findNoProfitLockerAccounts", limit);
	}

	@Override
	public boolean clearProfitLocker() {
		return updateDao.update("CURRENT_ACCOUNT.clearProfitLocker", null) > 0;
	}

	@Transactional
	@Override
	public RedemptionResult redemption(RedemptionParam param) {
		AssertUtil.assertNotNull(param.getAmt(), "WITHDRAW_AMOUNT_NULL");
		AssertUtil.assertTrue(param.getAmt().compareTo(BigDecimal.ZERO) > 0, "WITHDRAW_AMOUNT_TOO_SMALL");
		UserDO userDO = userService.get(UserDO.class, param.getUid());
		AssertUtil.assertNotNull(userDO, "USER_NOT_EXIST");
		AssertUtil.assertTrue(userService.isUsedCurrentAccount(userDO.gethType()), "NOT_ENABLE_CURRENT_ACCOUNT");

		String dangerCode = userService.testDangerous(userDO.getId());
		AssertUtil.assertTrue(dangerCode == null, dangerCode);

		BigDecimal balance = getBalance(userDO.getId());
		AssertUtil.assertTrue(balance.compareTo(param.getAmt()) >= 0, "BALANCE_NOT_ENOUGH");

		JzhAccountDO jzhAccountDO = jzhAccountService.get(JzhAccountDO.class, userDO.getId());
		AssertUtil.assertNotNull(jzhAccountDO, "JZH_ACCOUNT_NOT_EXIST:未开通存管");

		// 扣款
		CurrentAccountItemDO currentAccountItemDO = subtract(userDO.getId(), param.getAmt(), "REDEMPTION", "");
		AssertUtil.assertNotNull(currentAccountItemDO, "SUBTRACT_BALANCE_FAIL");
		// 取现申请
		WithdrawDO withdrawDO = new WithdrawDO();
		withdrawDO.setApplyTime(new Date());
		withdrawDO.setId("ca_item-" + currentAccountItemDO.getId());
		withdrawDO.setStatus("transfered");
		withdrawDO.setWithdrawPrincipal(param.getAmt());
		withdrawDO.setUserId(userDO.getId());
		withdrawDO.setType("JZH-REDEMPTION");
		withdrawDO.setSubtractRemainProfit(BigDecimal.ZERO);
		AssertUtil.assertTrue(withdrawService.create(withdrawDO), "CREATE_WITHDRAWDO_ERROR");
		// 活期借款人
		RegistryDO registryDO = registryService.get(RegistryDO.class, "sys.h.borrower");
		AssertUtil.assertNotNull(registryDO, "BORROWER_NOT_EXIST:借款人不存在");
		BorrowerDO borrowerDO = borrowerService.get(BorrowerDO.class, registryDO.getVal().trim());
		AssertUtil.assertNotNull(borrowerDO, "BORROWERDO_NOT_EXIST:借款人不存在");
		// 借款人打给投资人
		JzhRemoteTransferBuService.Param jzhTransferParam = new JzhRemoteTransferBuService.Param();
		jzhTransferParam.setInCustNo(jzhAccountDO.getMobileNo());
		jzhTransferParam.setOutCustNo(borrowerDO.getMobile());
		jzhTransferParam.setMchntTxnSsn(jzhAccountDO.getMobileNo() + "_" + System.currentTimeMillis());
		jzhTransferParam.setCentAmt(param.getAmt().multiply(BigDecimal.valueOf(100)).longValue());
		jzhTransferParam.setRem("赎回");
		jzhTransferParam.setContractNo("");
		JzhRemoteTransferBuService.Result transferResult = jzhRemoteTransferBuService.post(jzhTransferParam);
		AssertUtil.assertNotNull(transferResult, "JZH_RESULT_NULL");
		AssertUtil.assertTrue("0000".equals(transferResult.getRespCode()), transferResult.getRespCode() + ":" + transferResult.getRespDesc());
		// 本地账户余额加钱
		BigDecimal jzhBalance = jzhAccountService.add(userDO.getId(), param.getAmt(), "redemption_" + transferResult.getMchntTxnSsn(), "redemption", "充值");
		AssertUtil.assertNotNull(jzhBalance, "ADD_BALANCE_FAIL");

		RedemptionResult redemptionResult = new RedemptionResult();
		redemptionResult.setBalance(jzhBalance);
		redemptionResult.setWithdrawId(withdrawDO.getId());
		return redemptionResult;
	}

	@Transactional
	@Override
	public RedemptionResult redemptionApply(RedemptionParam param) {
		AssertUtil.assertNotNull(param.getAmt(), "WITHDRAW_AMOUNT_NULL");
		AssertUtil.assertTrue(param.getAmt().compareTo(BigDecimal.ZERO) > 0, "WITHDRAW_AMOUNT_TOO_SMALL");
		UserDO userDO = userService.get(UserDO.class, param.getUid());
		AssertUtil.assertNotNull(userDO, "USER_NOT_EXIST");
		AssertUtil.assertTrue(userService.isUsedCurrentAccount(userDO.gethType()), "NOT_ENABLE_CURRENT_ACCOUNT");

		String dangerCode = userService.testDangerous(userDO.getId());
		AssertUtil.assertTrue(dangerCode == null, dangerCode);

		BigDecimal balance = getBalance(userDO.getId());
		AssertUtil.assertTrue(balance.compareTo(param.getAmt()) >= 0, "BALANCE_NOT_ENOUGH");

		JzhAccountDO jzhAccountDO = jzhAccountService.get(JzhAccountDO.class, userDO.getId());
		AssertUtil.assertNotNull(jzhAccountDO, "JZH_ACCOUNT_NOT_EXIST:未开通存管");

		// 扣款
		CurrentAccountItemDO currentAccountItemDO = subtract(userDO.getId(), param.getAmt(), "REDEMPTION", "");
		AssertUtil.assertNotNull(currentAccountItemDO, "SUBTRACT_BALANCE_FAIL");
		// 取现申请
		WithdrawDO withdrawDO = new WithdrawDO();
		withdrawDO.setApplyTime(new Date());
		withdrawDO.setId("ca_item-" + currentAccountItemDO.getId());
		withdrawDO.setStatus("apply");
		withdrawDO.setWithdrawPrincipal(param.getAmt());
		withdrawDO.setUserId(userDO.getId());
		withdrawDO.setType("JZH-REDEMPTION");
		withdrawDO.setSubtractRemainProfit(BigDecimal.ZERO);
		AssertUtil.assertTrue(withdrawService.create(withdrawDO), "CREATE_WITHDRAWDO_ERROR");
		RedemptionResult redemptionResult = new RedemptionResult();
		redemptionResult.setWithdrawId(withdrawDO.getId());
		return redemptionResult;
	}

	@Transactional
	@Override
	public boolean redemptionTransfer(String withdrawId) {

		WithdrawDO withdrawDO = withdrawService.get(WithdrawDO.class, withdrawId);
		AssertUtil.assertNotNull(withdrawDO, "WITHDRAW_DO_NOT_EXIST:赎回请求不存在");
		AssertUtil.assertTrue("apply".equalsIgnoreCase(withdrawDO.getStatus()), "WITHDRAW_DO_STATUS_ERROR:赎回状态错误");
		withdrawDO.setStatus("transfered");
		AssertUtil.assertTrue(withdrawService.updateSkipCheckOwner(withdrawDO), "UPDATE_TRANSFERED_FAIL:标识已回款失败");

		JzhAccountDO jzhAccountDO = jzhAccountService.get(JzhAccountDO.class, withdrawDO.getUserId());
		// 活期借款人
		RegistryDO registryDO = registryService.get(RegistryDO.class, "sys.h.borrower");
		AssertUtil.assertNotNull(registryDO, "BORROWER_NOT_EXIST:借款人不存在");
		BorrowerDO borrowerDO = borrowerService.get(BorrowerDO.class, registryDO.getVal().trim());
		AssertUtil.assertNotNull(borrowerDO, "BORROWERDO_NOT_EXIST:借款人不存在");
		// 借款人打给投资人
		JzhRemoteTransferBuService.Param jzhTransferParam = new JzhRemoteTransferBuService.Param();
		jzhTransferParam.setInCustNo(jzhAccountDO.getMobileNo());
		jzhTransferParam.setOutCustNo(borrowerDO.getMobile());
		jzhTransferParam.setMchntTxnSsn(jzhAccountDO.getMobileNo() + "_" + System.currentTimeMillis());
		jzhTransferParam.setCentAmt(withdrawDO.getWithdrawPrincipal().multiply(BigDecimal.valueOf(100)).longValue());
		jzhTransferParam.setRem("赎回");
		jzhTransferParam.setContractNo("");
		JzhRemoteTransferBuService.Result transferResult = jzhRemoteTransferBuService.post(jzhTransferParam);
		AssertUtil.assertNotNull(transferResult, "JZH_RESULT_NULL");
		AssertUtil.assertTrue("0000".equals(transferResult.getRespCode()), transferResult.getRespCode() + ":" + transferResult.getRespDesc());
		// 本地账户余额加钱
		BigDecimal jzhBalance = jzhAccountService.add(withdrawDO.getUserId(), withdrawDO.getWithdrawPrincipal(), "redemption_" + transferResult.getMchntTxnSsn(), "redemption", "赎回");
		AssertUtil.assertNotNull(jzhBalance, "ADD_BALANCE_FAIL");

		return true;
	}

	private final static String T0_REDEMPTION_BALANCE_KEY = "sys.t0.redemption.balance";
	private final static String T0_REDEMPTION_BALANCE_FIELD_LIMIT = "limit";
	private final static String T0_REDEMPTION_BALANCE_FIELD_USED = "used";
	private final static String T0_REDEMPTION_BALANCE_FIELD_BALANCE = "balance";

	@Override
	public T0RedemptionBalance getT0RedemptionBalance() {
		String todayKey = T0_REDEMPTION_BALANCE_KEY + DateUtil.formatDate(new Date());
		Map<String, String> value = CacheUtil.hgetAll(todayKey);
		T0RedemptionBalance balance = new T0RedemptionBalance();
		if (value == null || value.isEmpty()) {
			RegistryDO registryDO = registryService.get(RegistryDO.class, "sys.t0.redemption.balance");
			try {
				JSONObject json = (JSONObject) new JSONParser().parse(registryDO.getVal());
				BigDecimal defaultLimitAmt = BigDecimal.valueOf(Double.parseDouble(json.get("limit").toString()));
				Map<String, String> cacheValue = new HashMap();
				cacheValue.put(T0_REDEMPTION_BALANCE_FIELD_LIMIT, defaultLimitAmt.toString());
				cacheValue.put(T0_REDEMPTION_BALANCE_FIELD_BALANCE, defaultLimitAmt.toString());
				cacheValue.put(T0_REDEMPTION_BALANCE_FIELD_USED, "0");
				CacheUtil.hmset(todayKey, cacheValue);
				CacheUtil.expire(todayKey, 3600 * 25);
			} catch (Exception e) {
				balance.setBalance(BigDecimal.ZERO);
				balance.setDailyLimitAmt(BigDecimal.ZERO);
				balance.setUsedAmt(BigDecimal.ZERO);
				LOG.error("解析t0设置出错", e);
			}
		}
		try {
			value = CacheUtil.hgetAll(todayKey);
			balance.setBalance(BigDecimal.valueOf(Double.parseDouble(value.get(T0_REDEMPTION_BALANCE_FIELD_BALANCE))));
			balance.setDailyLimitAmt(BigDecimal.valueOf(Double.parseDouble(value.get(T0_REDEMPTION_BALANCE_FIELD_LIMIT))));
			balance.setUsedAmt(BigDecimal.valueOf(Double.parseDouble(value.get(T0_REDEMPTION_BALANCE_FIELD_USED))));
		} catch (Exception e) {
			balance.setBalance(BigDecimal.ZERO);
			balance.setDailyLimitAmt(BigDecimal.ZERO);
			balance.setUsedAmt(BigDecimal.ZERO);
			LOG.error("解析t0余额出错", e);
		}
		return balance;
	}

	@SuppressWarnings("unchecked")
	@Override
	public T0RedemptionBalance updateT0RedemptionLimitAmt(BigDecimal amt, boolean persistence) {
		AssertUtil.assertTrue(amt != null && amt.compareTo(BigDecimal.valueOf(0)) > 0, "AMT_ERROR");
		if (persistence) {
			JSONObject json = new JSONObject();
			json.put("limit", amt.toString());
			AssertUtil.assertTrue(registryService.update("sys.t0.redemption.balance", json.toJSONString()), "UPDATE_FAIL");
		}
		String todayKey = T0_REDEMPTION_BALANCE_KEY + DateUtil.formatDate(new Date());

		T0RedemptionBalance balance = this.getT0RedemptionBalance();
		balance.setBalance(amt.subtract(balance.getUsedAmt()));
		balance.setDailyLimitAmt(amt);
		CacheUtil.hset(todayKey, T0_REDEMPTION_BALANCE_FIELD_LIMIT, amt.toString());
		CacheUtil.hset(todayKey, T0_REDEMPTION_BALANCE_FIELD_BALANCE, balance.getBalance().toString());
		CacheUtil.expire(todayKey, 3600 * 25);
		return balance;
	}

	@Override
	public BigDecimal subtractT0Balance(BigDecimal amt) {
		String todayKey = T0_REDEMPTION_BALANCE_KEY + DateUtil.formatDate(new Date());
		Map<String, String> map = CacheUtil.hgetAll(todayKey);
		if (map == null) {
			getT0RedemptionBalance();
			map = CacheUtil.hgetAll(todayKey);
		}
		map.put(T0_REDEMPTION_BALANCE_FIELD_BALANCE, BigDecimal.valueOf(Double.parseDouble(map.get(T0_REDEMPTION_BALANCE_FIELD_BALANCE))).subtract(amt).toString());
		map.put(T0_REDEMPTION_BALANCE_FIELD_USED, BigDecimal.valueOf(Double.parseDouble(map.get(T0_REDEMPTION_BALANCE_FIELD_USED))).add(amt).toString());

		CacheUtil.hset(todayKey, T0_REDEMPTION_BALANCE_FIELD_BALANCE, map.get(T0_REDEMPTION_BALANCE_FIELD_BALANCE));
		CacheUtil.hset(todayKey, T0_REDEMPTION_BALANCE_FIELD_USED, map.get(T0_REDEMPTION_BALANCE_FIELD_USED));
		return BigDecimal.ZERO;
	}
}
